package com.tz.advice;


import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * Created by Administrator on 2017/1/6.
 */
@Component
@Aspect  //当前类中包含切面的配置信息, Aspect = advice + pointcut
        // advice 的方法，代表要做什么
        // pointcut 部份 = @Before + execution, 代表where, when, 也就是这个切面加上哪儿，何时做
public class LogAdvice {

    //jp 就是对现场信息的封装
    @Before("execution(public * com.tz.hello.SimpleHello.*(..))")
//    @After("execution(public * com.tz.hello.SimpleHello.*(..))")   //不管目标方法是否有异常，都将执行这个切面
//    @AfterReturning("execution(public * com.tz.hello.SimpleHello.*(..))") //只有当目标方法正常返回后，才执行这个切面
//    @AfterThrowing("execution(public * com.tz.hello.SimpleHello.*(..))")  //只有当目标方法抛出异常后，才执行这个切面
    void before_log(JoinPoint jp) {
//      Object log(ProceedingJoinPoint jp) {
        String methodName = jp.getSignature().getName(); //获取方法名
        String className = jp.getTarget().getClass().getSimpleName(); //获取简单类名
        //
        System.out.printf("[%s] 类的 [%s]方法执行之前：%s\n", className, methodName, new Date());
    }


    /****************
     * 采用环繞的方式，需要接收另一个参数：ProceedingJoinPoint ，这个是继承于 JoinPoint 类的
     * 这个类型中有 proceed 方法，这个方法决定是否要到目标类的目标方法去。
     * @param pjp
     * @return
     */
    @Around("execution(public * com.tz.hello.SimpleHello.*(..))")  //环繞
    Object around_log(ProceedingJoinPoint pjp) { //参数要改成 ProceedingJoinPoint pjp
        Object result = null;
        try {
            System.out.println("*** 目标方法之前.....");
            result = pjp.proceed(); //调用目标方法
            System.out.println("*** 目标方法正确执行之后");
        } catch (Throwable throwable) {
            System.out.println("*** 出现异常后....");
            throwable.printStackTrace();
        }
        return result;
    }

    @After("@annotation(com.tz.annotations.Hehe)")  //只有打上了 @Hehe 注解的方法调用之后才会调用此横切逻辑
    public void after_log(JoinPoint jp) {
        System.out.printf("在 %s 方法调用之后.....\n", jp.getSignature().getName());
    }
}
